Introduction
Our group would like to study employee attrition using the Employee
Attrition dataset from Kaggle. As there is potentially identifying
information about individuals, this dataset is a fictional dataset
created by IBM data scientists to protect the privacy, while simulating
real employee information in a typical biomedical company.
In the job market, it is relatively rare for an individual to stay
forever in one company for the entire career life. Oftentimes, people
move on to a different company, hopefully for better income or treatment
potentials; people might have to switch jobs due to family reasons and
change of address; in some situations, employees might be forced to
leave, either due to company restructuring and layoffs, or just poor
individual job performance. Employee attrition could refer to any of the
above circumstances and many more, when an employee leaves the company
they work for for any reason, both voluntarily or involuntarily.
Employee attrition, of course, is normal. Certain employee attrition
is inevitable–retirement, illness, laying off, etc; but many other types
are manageable–the company can always attract employees by making their
work enjoyable for them. It is highly important for human resources to
keep track of employee attrition statistics, especially in positions
where work experience and training is essential. If companies have a
high attrition proportion, it might signal poor income potential, poor
working environment, or the companies’ poor future prospects; and it
could often lead to problems such as gap in worker training and
discontinuity, which might lead to greater attrition, creating a vicious
cycle. Thus, a well-functioning company should consciously keep track of
its employee attrition statistics, and seek remedy when attrition
statistics seem to go out of control.
Brief Intro to Data
Our Kaggle dataset contains the information of 1470 employees with 35
variables. The variables include employees’ demographic variables
(binary gender, age, education, marriage status, etc.), career
information (job role, job involvement, department, working years,
salary, etc.), job satisfaction measure (work-life balance,
job/relationship/environment satisfaction), performance rating, and
other miscellaneous information. Unfortunately, there is no such
variable that informs if the attrition is voluntary or involuntary.
However, we could still gather a good amount of information and explore
what are the potential factors behind attrition. Given that this is a
fictional dataset referring to no specific companies, we will not make
any judgements on whether one statistics is too high or one aspect is
abnormal; we simply aim to explore potential causes and correlation with
attrition status.
Analysis
1. Employee Demographics
Age
We first wish to explore the age distribution of employees, and in
particular, the age differential between those who have left the job and
those who haven’t.

As shown above, the age range of employees spans widely, all the way
from 18 to 60 years old, and the distribution is roughly bell shaped but
somewhat right-skewed, with those who age between 25-40 being the major
workforce. Overall, we see that those who have left the company tend to
be younger than those who haven’t with more left-skewness in the age
distribution, which is to be expected as younger people with fewer work
experiences tend to seek more potentials by switching jobs, though we
find that such difference isn’t quite large. In addition, we also find
noticeable spikes in age with roughly similar intervals in between.
Given the data sample size isn’t quite small, we can suspect that there
might be certain recruitment reasons on the companies side other than
total randomness. One possible reason is that the company might be
actively seeking college graduates every other year, which might explain
the roughly similarly-spaced spikes.

Following the line, it is not surprising that it shows a similar
pattern when dividing the employees by departments in general.
Nevertheless, there are some differences among departments. For Sales,
both lines for attrited and not-attrited follow the same progression
across age, indicating that attrition mainly follows the change of
employee size in the company. Though we are restricted to the small data
size for the human resources department, we can tell that age is a more
important factor than employee size in describing employee attrition.
For the research and development department, we can inspect in two
parts. The first part– age 18 to age around 32– both lines progress in a
very similar way. In contrast, the two lines start to diverge around age
32: non-attrition increases and decreases while attrition decreases and
then remains at a relatively small size of people. One possible
explanation is that research and development requires a lot of
pre-effort before actually gaining some response. Meaning the time
before it is just sunk cost. Thus, some might prefer to stop loss in
time by starting a new career when they still have a chance while some
others prefer to stay in the field.
Gender

In general, the employee attrition rate is about 16%, and we cannot
discern an obvious distinction of attrition rate between male and
females. We can, however, notice that the company generally employs more
males than females. To get a sense of gender distribution across
departments, we also draw the mosaic plot below. We find that males have
the highest proportion in the Human Resource department, though there is
also considerable disparity in the other two departments.

Attrition vs. years at company
To get a sense of typically how long an employee stays in a company,
I draw a Kaplan-Meier survival curve of employees, as shown in the graph
below.

The x-axis stands for years at a company for an individual, and the
y-axis stands for the proportion of employees that still stays at the
company, or the “survival” rate of employees. Mathematically, we could
represent it as \(P(Survival)=1-P({Attrition})\) From the
curve, we find that about half of all employees leave the company within
5 years, and only 20% of all employees will stay within the company for
ten years.
2. Relationship between attrition and Income
One big factor that an employee quits the company is that they are
not satisfied with their income and seek to find other jobs with higher
income prospects. For this reason, we wish to explore the overall income
status of employees. Note: as the Kaggle dataset did not provide the
currency unit for income, we will also not include units for income in
our analysis.
The above histogram describes the overall income distribution by
attrition status, with the smoothed green density. Overall, we observe a
good amount of income disparity–the skewed distribution shows that most
workers receive a monthly income lower than the average, while a few
people receive a monthly income far higher than the average income in
this company. In addition, we find that the income disparity seems more
extreme within the attrited employees with much greater skewness and
greater percentage earning less than 5,000 a month, and very small
percentage of employees earning over 10,000 left the company. This
provides certain evidence that income prospects are quite related with
attrition status.

We then take a step further into the monthly income distribution by
department and attrition status. The boxplots above show that, among the
three departments, human resources and research & development
departments tend to have greater income inequality as we see relatively
larger gaps between the median and the average income (shown by the dark
brown line). At the same time, it seems that in these two departments,
non-attrited employees tend to have much higher monthly income than
those who left the company. Income inequality and
attrition/non-attrition differential is less extreme for the sales
department, but the lower-interquartile difference is still substantial.
Overall, the sales department has the highest average monthly income
6959.2, the human resources department has the second highest average
monthly income 6654.5, and the research & development department has
the lowest average monthly income 6281.3.
In addition to the current income status, probably even more,
employees care about how likely their income would increase in the
future. We thus draw the scatter plot below to show the relationship
between average monthly income and years at company. If we ignore the
outliers who left the company after over 30 years serving for the
company, we find that the prospect of pay raise is roughly the same
between those both attrition groups, as we see a roughly parallel
trend.

We look more closely at the percent salary hike by department in the
group of boxplots below. The results corroborate the previous graph.
Other than the human resources department which have the fewest
employees, in both R&D and Sales departments, the income prospects
for those who have and haven’t left the company is approximately the
same, with very similar median, mean, and interquartile salary hike
percentage. Thus, from this data, we don’t think future income prospects
play as huge a role in attrition status as the current income.

3. Relationship between Job Satisfaction and Attrition
Probably even more important than income, employees’ overall job
satisfaction ratings could potentially tell more about whether they are
happy with their job. We thus also wish to explore the relationship
between attrition and job satisfaction. In our dataset, job rating has
four levels: 1 meaning “low,” 2 meaning “medium,” 3 meaning “high,” 4
meaning “very high.”
When looking at job satisfaction, it is unsurprising that the
employees who rated “1” would more tend to leave the company in general.
In addition, for the human resources department, half of the employees
rated “1” attrited. However, it is interesting to note that there are
even less employees attrited with rating “2” than other two higher
ratings. Moreover, for the other two departments, although the attrition
decreases with the increase of rating, the attrition differences among
different ratings are not explicit. Thus, job satisfaction might not be
a very informative influence when evaluating the attrition. Some
possible explanations might be that employees’ rating might vary over
time or some might not treat the rating seriously enough to respond with
a valid value.
#Conclusion
Employee attrition is an important piece of information to keep track
of for any large company, as it deeply concerns employees’ morale, work
environment, and production continuity of the organization. In our
Kaggle dataset, overall, we find that employee attrition appears to have
the greatest correlation with income levels, while future income
prospects and job satisfaction ratings seem less important factors. This
has been informative for us and especially for human resources to
understand the general trend and explanatory factors of employee
attrition.
However, we also admittedly face limitations with our dataset. First,
while we appreciate that the fictional dataset protects individual
privacy, as we cannot identify any specific company, we don’t know how
typical our data is and if the data can well represent all similar
biomedical companies. Second, since we cannot track whether attrition is
voluntary or not, we face restrictions in drawing more meaningful
conclusions from our data. If we were able to locate the data more
specifically at voluntary attrition, we might be able to more closely
identify potential reasons from the companies’ side for employees
quitting. Finally, given that our dataset, while reasonably large enough
for us to make visual representations, does not contain quite many
attrited data points(about over 200), and contains only three
departments (Sales, R&D, Human resources), we couldn’t reasonably
include all or as many variables as we desire, as that would leave too
few data points in each group.
LS0tDQp0aXRsZTogIlNUQVQxMTIgUHJvamVjdC0tRW1wbG95ZWUgQXR0cml0aW9uIg0KYXV0aG9yOiAiSmVubnkgTGksIEdldmVuIExpdSwgV2VueHVhbiBaaHUiDQpkYXRlOiAnMjAyMi0wNC0xNicNCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgdGhlbWU6IHNpbXBsZXgNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IEZBTFNFLCBlcnJvcj1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQ0KYGBgDQoNCmBgYHtyIGxpYnJhcmllcyxtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ21vc2FpYykNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShnZ3RoZW1lcykgDQpsaWJyYXJ5KGdlb2ZhY2V0KQ0KbGlicmFyeShvcGVuaW50cm8pDQpsaWJyYXJ5KGdwbG90cykNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShnZ3RoZW1lcykgICAgIA0KbGlicmFyeShwbG90bHkpIA0KbGlicmFyeShnZ2FuaW1hdGUpDQpsaWJyYXJ5KGdpZnNraSkgDQpsaWJyYXJ5KHRyYW5zZm9ybXIpIA0KbGlicmFyeShwYXRjaHdvcmspIA0KbGlicmFyeShzdXJ2aXZhbCkNCmxpYnJhcnkoc2YpICAgICAgICAgIA0KbGlicmFyeShnZ3RoZW1lcykgICAgICANCmxpYnJhcnkoZ2dhbmltYXRlKSAgICAgDQpsaWJyYXJ5KHRyYW5zZm9ybXIpICAgIA0KbGlicmFyeShnaWZza2kpICAgICAgICANCmxpYnJhcnkocmVhZHIpDQp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uIA0KDQo+T3VyIGdyb3VwIHdvdWxkIGxpa2UgdG8gc3R1ZHkgZW1wbG95ZWUgYXR0cml0aW9uIHVzaW5nIHRoZSBbRW1wbG95ZWUgQXR0cml0aW9uIGRhdGFzZXRdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvcGF2YW5zdWJoYXNodC9pYm0taHItYW5hbHl0aWNzLWF0dHJpdGlvbi1kYXRhc2V0KSBmcm9tIEthZ2dsZS4gQXMgdGhlcmUgaXMgcG90ZW50aWFsbHkgaWRlbnRpZnlpbmcgaW5mb3JtYXRpb24gYWJvdXQgaW5kaXZpZHVhbHMsIHRoaXMgZGF0YXNldCBpcyBhIGZpY3Rpb25hbCBkYXRhc2V0IGNyZWF0ZWQgYnkgSUJNIGRhdGEgc2NpZW50aXN0cyB0byBwcm90ZWN0IHRoZSBwcml2YWN5LCB3aGlsZSBzaW11bGF0aW5nIHJlYWwgZW1wbG95ZWUgaW5mb3JtYXRpb24gaW4gYSB0eXBpY2FsIGJpb21lZGljYWwgY29tcGFueS4NCg0KPkluIHRoZSBqb2IgbWFya2V0LCBpdCBpcyByZWxhdGl2ZWx5IHJhcmUgZm9yIGFuIGluZGl2aWR1YWwgdG8gc3RheSBmb3JldmVyIGluIG9uZSBjb21wYW55IGZvciB0aGUgZW50aXJlIGNhcmVlciBsaWZlLiBPZnRlbnRpbWVzLCBwZW9wbGUgbW92ZSBvbiB0byBhIGRpZmZlcmVudCBjb21wYW55LCBob3BlZnVsbHkgZm9yIGJldHRlciBpbmNvbWUgb3IgdHJlYXRtZW50IHBvdGVudGlhbHM7IHBlb3BsZSBtaWdodCBoYXZlIHRvIHN3aXRjaCBqb2JzIGR1ZSB0byBmYW1pbHkgcmVhc29ucyBhbmQgY2hhbmdlIG9mIGFkZHJlc3M7IGluIHNvbWUgc2l0dWF0aW9ucywgZW1wbG95ZWVzIG1pZ2h0IGJlIGZvcmNlZCB0byBsZWF2ZSwgZWl0aGVyIGR1ZSB0byBjb21wYW55IHJlc3RydWN0dXJpbmcgYW5kIGxheW9mZnMsIG9yIGp1c3QgcG9vciBpbmRpdmlkdWFsIGpvYiBwZXJmb3JtYW5jZS4gRW1wbG95ZWUgYXR0cml0aW9uIGNvdWxkIHJlZmVyIHRvIGFueSBvZiB0aGUgYWJvdmUgY2lyY3Vtc3RhbmNlcyBhbmQgbWFueSBtb3JlLCB3aGVuIGFuIGVtcGxveWVlIGxlYXZlcyB0aGUgY29tcGFueSB0aGV5IHdvcmsgZm9yIGZvciBhbnkgcmVhc29uLCBib3RoIHZvbHVudGFyaWx5IG9yIGludm9sdW50YXJpbHkuDQoNCj5FbXBsb3llZSBhdHRyaXRpb24sIG9mIGNvdXJzZSwgaXMgbm9ybWFsLiBDZXJ0YWluIGVtcGxveWVlIGF0dHJpdGlvbiBpcyBpbmV2aXRhYmxlLS1yZXRpcmVtZW50LCBpbGxuZXNzLCBsYXlpbmcgb2ZmLCBldGM7IGJ1dCBtYW55IG90aGVyIHR5cGVzIGFyZSBtYW5hZ2VhYmxlLS10aGUgY29tcGFueSBjYW4gYWx3YXlzIGF0dHJhY3QgZW1wbG95ZWVzIGJ5IG1ha2luZyB0aGVpciB3b3JrIGVuam95YWJsZSBmb3IgdGhlbS4gSXQgaXMgaGlnaGx5IGltcG9ydGFudCBmb3IgaHVtYW4gcmVzb3VyY2VzIHRvIGtlZXAgdHJhY2sgb2YgZW1wbG95ZWUgYXR0cml0aW9uIHN0YXRpc3RpY3MsIGVzcGVjaWFsbHkgaW4gcG9zaXRpb25zIHdoZXJlIHdvcmsgZXhwZXJpZW5jZSBhbmQgdHJhaW5pbmcgaXMgZXNzZW50aWFsLiBJZiBjb21wYW5pZXMgaGF2ZSBhIGhpZ2ggYXR0cml0aW9uIHByb3BvcnRpb24sIGl0IG1pZ2h0IHNpZ25hbCBwb29yIGluY29tZSBwb3RlbnRpYWwsIHBvb3Igd29ya2luZyBlbnZpcm9ubWVudCwgb3IgdGhlIGNvbXBhbmllcycgcG9vciBmdXR1cmUgcHJvc3BlY3RzOyBhbmQgaXQgY291bGQgb2Z0ZW4gbGVhZCB0byBwcm9ibGVtcyBzdWNoIGFzIGdhcCBpbiB3b3JrZXIgdHJhaW5pbmcgYW5kIGRpc2NvbnRpbnVpdHksIHdoaWNoIG1pZ2h0IGxlYWQgdG8gZ3JlYXRlciBhdHRyaXRpb24sIGNyZWF0aW5nIGEgdmljaW91cyBjeWNsZS4gVGh1cywgYSB3ZWxsLWZ1bmN0aW9uaW5nIGNvbXBhbnkgc2hvdWxkIGNvbnNjaW91c2x5IGtlZXAgdHJhY2sgb2YgaXRzIGVtcGxveWVlIGF0dHJpdGlvbiBzdGF0aXN0aWNzLCBhbmQgc2VlayByZW1lZHkgd2hlbiBhdHRyaXRpb24gc3RhdGlzdGljcyBzZWVtIHRvIGdvIG91dCBvZiBjb250cm9sLg0KDQojIyBCcmllZiBJbnRybyB0byBEYXRhDQo+T3VyIEthZ2dsZSBkYXRhc2V0IGNvbnRhaW5zIHRoZSBpbmZvcm1hdGlvbiBvZiAxNDcwIGVtcGxveWVlcyB3aXRoIDM1IHZhcmlhYmxlcy4gVGhlIHZhcmlhYmxlcyBpbmNsdWRlIGVtcGxveWVlcycgZGVtb2dyYXBoaWMgdmFyaWFibGVzIChiaW5hcnkgZ2VuZGVyLCBhZ2UsIGVkdWNhdGlvbiwgbWFycmlhZ2Ugc3RhdHVzLCBldGMuKSwgY2FyZWVyIGluZm9ybWF0aW9uIChqb2Igcm9sZSwgam9iIGludm9sdmVtZW50LCBkZXBhcnRtZW50LCB3b3JraW5nIHllYXJzLCBzYWxhcnksIGV0Yy4pLCBqb2Igc2F0aXNmYWN0aW9uIG1lYXN1cmUgKHdvcmstbGlmZSBiYWxhbmNlLCBqb2IvcmVsYXRpb25zaGlwL2Vudmlyb25tZW50IHNhdGlzZmFjdGlvbiksIHBlcmZvcm1hbmNlIHJhdGluZywgYW5kIG90aGVyIG1pc2NlbGxhbmVvdXMgaW5mb3JtYXRpb24uIFVuZm9ydHVuYXRlbHksIHRoZXJlIGlzIG5vIHN1Y2ggdmFyaWFibGUgdGhhdCBpbmZvcm1zIGlmIHRoZSBhdHRyaXRpb24gaXMgdm9sdW50YXJ5IG9yIGludm9sdW50YXJ5LiBIb3dldmVyLCB3ZSBjb3VsZCBzdGlsbCBnYXRoZXIgYSBnb29kIGFtb3VudCBvZiBpbmZvcm1hdGlvbiBhbmQgZXhwbG9yZSB3aGF0IGFyZSB0aGUgcG90ZW50aWFsIGZhY3RvcnMgYmVoaW5kIGF0dHJpdGlvbi4gR2l2ZW4gdGhhdCB0aGlzIGlzIGEgZmljdGlvbmFsIGRhdGFzZXQgcmVmZXJyaW5nIHRvIG5vIHNwZWNpZmljIGNvbXBhbmllcywgd2Ugd2lsbCBub3QgbWFrZSBhbnkganVkZ2VtZW50cyBvbiB3aGV0aGVyIG9uZSBzdGF0aXN0aWNzIGlzIHRvbyBoaWdoIG9yIG9uZSBhc3BlY3QgaXMgYWJub3JtYWw7IHdlIHNpbXBseSBhaW0gdG8gZXhwbG9yZSBwb3RlbnRpYWwgY2F1c2VzIGFuZCBjb3JyZWxhdGlvbiB3aXRoIGF0dHJpdGlvbiBzdGF0dXMuDQoNCmBgYHtyIERhdGF9DQpFbXBsb3llZSA8LSByZWFkX2NzdigiRW1wbG95ZWUuY3N2IikNCmBgYA0KDQojIEFuYWx5c2lzDQoNCiMjIDEuIEVtcGxveWVlIERlbW9ncmFwaGljcw0KDQojIyMgQWdlDQoNCj5XZSBmaXJzdCB3aXNoIHRvIGV4cGxvcmUgdGhlIGFnZSBkaXN0cmlidXRpb24gb2YgZW1wbG95ZWVzLCBhbmQgaW4gcGFydGljdWxhciwgdGhlIGFnZSBkaWZmZXJlbnRpYWwgYmV0d2VlbiB0aG9zZSB3aG8gaGF2ZSBsZWZ0IHRoZSBqb2IgYW5kIHRob3NlIHdobyBoYXZlbid0Lg0KDQpgYGB7cixmaWcuYWx0PSJBZ2UgZGlzdHJpYnV0aW9uIG9mIGVtcGxveWVlcy4gQ29tYmluYXRpb24gb2YgdGhyZWUgcGxvdHM6IHRoZSBwbG90IG9mIHRoZSBsZWZ0IGluY2x1ZGVzIGFsbCBlbXBsb3llZXMsIHRoZSBwbG90IG9uIHRoZSB0b3AgcmlnaHQgaW5jbHVkZXMgdGhvc2Ugd2l0aCBhdHRyaXRpb249WUVTLCB0aGUgcGxvdCBvbiB0aGUgYm90dG9tIHJpZ2h0IGluY2x1ZGVzIHRob3NlIHdpdGggYXR0cml0aW9uPU5PIn0NCmF0IDwtIEVtcGxveWVlICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBBZ2UpKSArDQogIGdlb21faGlzdG9ncmFtKGNvbG9yID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgICAgZmlsbCA9ICJncmF5NjUiKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGxhYnModGl0bGUgPSAiQWxsIGVtcGxveWVlcyIsIHkgPSAiIikNCg0KYXR5PC1FbXBsb3llZSAlPiUNCiAgZmlsdGVyKEF0dHJpdGlvbj09IlllcyIpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9QWdlKSkrDQogIGdlb21faGlzdG9ncmFtKGNvbG9yID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgICAgZmlsbCA9ICJicm93bjQiKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICBsYWJzKHRpdGxlPSJBdHRyaXRlZCIseT0iIix4PSIiKQ0KDQphdG48LUVtcGxveWVlICU+JQ0KICBmaWx0ZXIoQXR0cml0aW9uPT0iTm8iKSAlPiUNCiAgZ2dwbG90KGFlcyh4PUFnZSkpKw0KICBnZW9tX2hpc3RvZ3JhbShjb2xvciA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgIGZpbGwgPSAiZG9kZ2VyYmx1ZTQiKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICBsYWJzKHRpdGxlPSJOb24tYXR0cml0ZWQiLHk9IiIpDQoNCmF0ICsgKGF0eS9hdG4pICArIA0KICBwbG90X2Fubm90YXRpb24odGl0bGUgPSAiQWdlIGRpc3RyaWJ1dGlvbiBvZiBlbXBsb3llZXMiKSANCmBgYA0KDQo+QXMgc2hvd24gYWJvdmUsIHRoZSBhZ2UgcmFuZ2Ugb2YgZW1wbG95ZWVzIHNwYW5zIHdpZGVseSwgYWxsIHRoZSB3YXkgZnJvbSAxOCB0byA2MCB5ZWFycyBvbGQsIGFuZCB0aGUgZGlzdHJpYnV0aW9uIGlzIHJvdWdobHkgYmVsbCBzaGFwZWQgYnV0IHNvbWV3aGF0IHJpZ2h0LXNrZXdlZCwgd2l0aCB0aG9zZSB3aG8gYWdlIGJldHdlZW4gMjUtNDAgYmVpbmcgdGhlIG1ham9yIHdvcmtmb3JjZS4gT3ZlcmFsbCwgd2Ugc2VlIHRoYXQgdGhvc2Ugd2hvIGhhdmUgbGVmdCB0aGUgY29tcGFueSB0ZW5kIHRvIGJlIHlvdW5nZXIgdGhhbiB0aG9zZSB3aG8gaGF2ZW4ndCB3aXRoIG1vcmUgbGVmdC1za2V3bmVzcyBpbiB0aGUgYWdlIGRpc3RyaWJ1dGlvbiwgd2hpY2ggaXMgdG8gYmUgZXhwZWN0ZWQgYXMgeW91bmdlciBwZW9wbGUgd2l0aCBmZXdlciB3b3JrIGV4cGVyaWVuY2VzIHRlbmQgdG8gc2VlayBtb3JlIHBvdGVudGlhbHMgYnkgc3dpdGNoaW5nIGpvYnMsIHRob3VnaCB3ZSBmaW5kIHRoYXQgc3VjaCBkaWZmZXJlbmNlIGlzbid0IHF1aXRlIGxhcmdlLiBJbiBhZGRpdGlvbiwgd2UgYWxzbyBmaW5kIG5vdGljZWFibGUgc3Bpa2VzIGluIGFnZSB3aXRoIHJvdWdobHkgc2ltaWxhciBpbnRlcnZhbHMgaW4gYmV0d2Vlbi4gR2l2ZW4gdGhlIGRhdGEgc2FtcGxlIHNpemUgaXNuJ3QgcXVpdGUgc21hbGwsIHdlIGNhbiBzdXNwZWN0IHRoYXQgdGhlcmUgbWlnaHQgYmUgY2VydGFpbiByZWNydWl0bWVudCByZWFzb25zIG9uIHRoZSBjb21wYW5pZXMgc2lkZSBvdGhlciB0aGFuIHRvdGFsIHJhbmRvbW5lc3MuIE9uZSBwb3NzaWJsZSByZWFzb24gaXMgdGhhdCB0aGUgY29tcGFueSBtaWdodCBiZSBhY3RpdmVseSBzZWVraW5nIGNvbGxlZ2UgZ3JhZHVhdGVzIGV2ZXJ5IG90aGVyIHllYXIsIHdoaWNoIG1pZ2h0IGV4cGxhaW4gdGhlIHJvdWdobHkgc2ltaWxhcmx5LXNwYWNlZCBzcGlrZXMuDQoNCmBgYHtyLGV2YWw9RkFMU0UsIGZpZy5hbHQ9IkNvbXBhcmlzaW9uIG9mIEF0dHJpdGVkIGFuZCBOb3QgQXR0cml0ZWQgRW1wbG95ZWUgTnVtYmVyIGJ5IERlcGFydG1lbnQgb3ZlciBBZ2UifQ0KbmV3RW1wbG95ZWUgPC0gRW1wbG95ZWUgJT4lDQogIGdyb3VwX2J5KERlcGFydG1lbnQsIEFnZSkgJT4lDQogIHN1bW1hcmlzZShhdHRyaXRlZCA9IHN1bShBdHRyaXRpb24gPT0gIlllcyIpLA0KICAgICAgICAgICAgbm90QXR0cml0ZWQgPSBzdW0oQXR0cml0aW9uID09ICJObyIpKSAlPiUNCiAgbXV0YXRlKG5ld0RlcGFydG1lbnQgPSBpZmVsc2UoDQogICAgRGVwYXJ0bWVudCA9PSAiU2FsZXMiLA0KICAgICJBdHRyaXRlZCBTYWxlcyIsDQogICAgaWZlbHNlKA0KICAgICAgRGVwYXJ0bWVudCA9PSAiSHVtYW4gUmVzb3VyY2VzIiwNCiAgICAgICJBdHRyaXRlZCBIdW1hbiBSZXNvdXJjZXMiLA0KICAgICAgaWZlbHNlKA0KICAgICAgICBEZXBhcnRtZW50ID09ICJSZXNlYXJjaCAmIERldmVsb3BtZW50IiwNCiAgICAgICAgIkF0dHJpdGVkIFJlc2VhcmNoICYgRGV2ZWxvcG1lbnQiLA0KICAgICAgICAiTkEiDQogICAgICApDQogICAgKQ0KICApKQ0KbmV3RW1wbG95ZWUgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gQWdlLCB5ID0gYXR0cml0ZWQsIGNvbG9yID0gRGVwYXJ0bWVudCksDQogICAgICAgICAgICBzaXplID0gMSwNCiAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gQWdlLCB5ID0gbm90QXR0cml0ZWQsIGNvbG9yID0gRGVwYXJ0bWVudCksIHNpemUgPSAxKSArDQogIGdlb21fdGV4dChhZXMoDQogICAgeCA9IEFnZSwNCiAgICB5ID0gbm90QXR0cml0ZWQsDQogICAgbGFiZWwgPSBEZXBhcnRtZW50LA0KICAgIGNvbG9yID0gRGVwYXJ0bWVudA0KICApKSArDQogIGdlb21fdGV4dChhZXMoDQogICAgeCA9IEFnZSwNCiAgICB5ID0gYXR0cml0ZWQsDQogICAgbGFiZWwgPSBuZXdEZXBhcnRtZW50LA0KICAgIGNvbG9yID0gbmV3RGVwYXJ0bWVudA0KICApKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29tcGFyaXNpb24gb2YgQXR0cml0ZWQgYW5kIE5vdCBBdHRyaXRlZCBFbXBsb3llZSBOdW1iZXIgYnkgRGVwYXJ0bWVudCBvdmVyIEFnZSIsDQogICAgc3VidGl0bGUgPSAiQWdlOiB7ZnJhbWVfYWxvbmd9IiwNCiAgICB4ID0gIiIsDQogICAgeSA9ICIiDQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJTYWxlcyIgPSAiYnJvd240IiwNCiAgICAgICJBdHRyaXRlZCBTYWxlcyIgPSAiYnJvd240IiwNCiAgICAgICJIdW1hbiBSZXNvdXJjZXMiID0gImRlZXBza3libHVlNCIsDQogICAgICAiQXR0cml0ZWQgSHVtYW4gUmVzb3VyY2VzIiA9ICJkZWVwc2t5Ymx1ZTQiLA0KICAgICAgIlJlc2VhcmNoICYgRGV2ZWxvcG1lbnQiID0gImdyYXk2NSIsDQogICAgICAiQXR0cml0ZWQgUmVzZWFyY2ggJiBEZXZlbG9wbWVudCIgPSAiZ3JheTY1Ig0KICAgICkNCiAgKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMwMDZiYjMiLCBzaXplID0gMTAuNSxmYWNlID0gImJvbGQiLGhqdXN0ID0gMSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMDA2YmIzIikNCiAgKSArDQogIHRyYW5zaXRpb25fcmV2ZWFsKGFzLmludGVnZXIoQWdlKSkNCmBgYA0KDQpgYGB7ciwgZXZhbD1GQUxTRSwgZWNobz1GQUxTRX0NCmFuaW1fc2F2ZSgiQ29tcGFyaXNpb24gb2YgQXR0cml0ZWQgYW5kIE5vdCBBdHRyaXRlZCBFbXBsb3llZSBOdW1iZXIgYnkgRGVwYXJ0bWVudCBvdmVyIEFnZS5naWYiKQ0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkNvbXBhcmlzaW9uIG9mIEF0dHJpdGVkIGFuZCBOb3QgQXR0cml0ZWQgRW1wbG95ZWUgTnVtYmVyIGJ5IERlcGFydG1lbnQgb3ZlciBBZ2UuZ2lmIikNCmBgYA0KDQo+Rm9sbG93aW5nIHRoZSBsaW5lLCBpdCBpcyBub3Qgc3VycHJpc2luZyB0aGF0IGl0IHNob3dzIGEgc2ltaWxhciBwYXR0ZXJuIHdoZW4gZGl2aWRpbmcgdGhlIGVtcGxveWVlcyBieSBkZXBhcnRtZW50cyBpbiBnZW5lcmFsLiBOZXZlcnRoZWxlc3MsIHRoZXJlIGFyZSBzb21lIGRpZmZlcmVuY2VzIGFtb25nIGRlcGFydG1lbnRzLiBGb3IgU2FsZXMsIGJvdGggbGluZXMgZm9yIGF0dHJpdGVkIGFuZCBub3QtYXR0cml0ZWQgZm9sbG93IHRoZSBzYW1lIHByb2dyZXNzaW9uIGFjcm9zcyBhZ2UsIGluZGljYXRpbmcgdGhhdCBhdHRyaXRpb24gbWFpbmx5IGZvbGxvd3MgdGhlIGNoYW5nZSBvZiBlbXBsb3llZSBzaXplIGluIHRoZSBjb21wYW55LiBUaG91Z2ggd2UgYXJlIHJlc3RyaWN0ZWQgdG8gdGhlIHNtYWxsIGRhdGEgc2l6ZSBmb3IgdGhlIGh1bWFuIHJlc291cmNlcyBkZXBhcnRtZW50LCB3ZSBjYW4gdGVsbCB0aGF0IGFnZSBpcyBhIG1vcmUgaW1wb3J0YW50IGZhY3RvciB0aGFuIGVtcGxveWVlIHNpemUgaW4gZGVzY3JpYmluZyBlbXBsb3llZSBhdHRyaXRpb24uIEZvciB0aGUgcmVzZWFyY2ggYW5kIGRldmVsb3BtZW50IGRlcGFydG1lbnQsIHdlIGNhbiBpbnNwZWN0IGluIHR3byBwYXJ0cy4gVGhlIGZpcnN0IHBhcnTigJMgYWdlIDE4IHRvIGFnZSBhcm91bmQgMzLigJMgYm90aCBsaW5lcyBwcm9ncmVzcyBpbiBhIHZlcnkgc2ltaWxhciB3YXkuIEluIGNvbnRyYXN0LCB0aGUgdHdvIGxpbmVzIHN0YXJ0IHRvIGRpdmVyZ2UgYXJvdW5kIGFnZSAzMjogbm9uLWF0dHJpdGlvbiBpbmNyZWFzZXMgYW5kIGRlY3JlYXNlcyB3aGlsZSBhdHRyaXRpb24gZGVjcmVhc2VzIGFuZCB0aGVuIHJlbWFpbnMgYXQgYSByZWxhdGl2ZWx5IHNtYWxsIHNpemUgb2YgcGVvcGxlLiBPbmUgcG9zc2libGUgZXhwbGFuYXRpb24gaXMgdGhhdCByZXNlYXJjaCBhbmQgZGV2ZWxvcG1lbnQgcmVxdWlyZXMgYSBsb3Qgb2YgcHJlLWVmZm9ydCBiZWZvcmUgYWN0dWFsbHkgZ2FpbmluZyBzb21lIHJlc3BvbnNlLiBNZWFuaW5nIHRoZSB0aW1lIGJlZm9yZSBpdCBpcyBqdXN0IHN1bmsgY29zdC4gVGh1cywgc29tZSBtaWdodCBwcmVmZXIgdG8gc3RvcCBsb3NzIGluIHRpbWUgYnkgc3RhcnRpbmcgYSBuZXcgY2FyZWVyIHdoZW4gdGhleSBzdGlsbCBoYXZlIGEgY2hhbmNlIHdoaWxlIHNvbWUgb3RoZXJzIHByZWZlciB0byBzdGF5IGluIHRoZSBmaWVsZC4NCg0KIyMjIEdlbmRlcg0KDQpgYGB7cixmaWcuYWx0PSJtb3NhaWMgcGxvdCBvZiBhdHRyaXRpb24oeSkgdnMgZ2VuZGVyKHgpIn0NCm1vc2FpY3Bsb3QoDQogIHRhYmxlKEVtcGxveWVlJEdlbmRlciwNCiAgICAgICAgRW1wbG95ZWUkQXR0cml0aW9uKSwNCiAgbWFpbiA9ICJBdHRyaXRpb24gdnMuIEdlbmRlciIsDQogIG9mZiA9IDMsDQogIGJvcmRlciA9ICJ3aGl0ZSIsDQogIGNvbG9yID0gMToyLA0KICBsYXMgPSAxLA0KICBjZXguYXhpcyAgPSAxDQopDQpgYGANCg0KPkluIGdlbmVyYWwsIHRoZSBlbXBsb3llZSBhdHRyaXRpb24gcmF0ZSBpcyBhYm91dCAxNiUsIGFuZCB3ZSBjYW5ub3QgZGlzY2VybiBhbiBvYnZpb3VzIGRpc3RpbmN0aW9uIG9mIGF0dHJpdGlvbiByYXRlIGJldHdlZW4gbWFsZSBhbmQgZmVtYWxlcy4gV2UgY2FuLCBob3dldmVyLCBub3RpY2UgdGhhdCB0aGUgY29tcGFueSBnZW5lcmFsbHkgZW1wbG95cyBtb3JlIG1hbGVzIHRoYW4gZmVtYWxlcy4gVG8gZ2V0IGEgc2Vuc2Ugb2YgZ2VuZGVyIGRpc3RyaWJ1dGlvbiBhY3Jvc3MgZGVwYXJ0bWVudHMsIHdlIGFsc28gZHJhdyB0aGUgbW9zYWljIHBsb3QgYmVsb3cuIFdlIGZpbmQgdGhhdCBtYWxlcyBoYXZlIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gaW4gdGhlIEh1bWFuIFJlc291cmNlIGRlcGFydG1lbnQsIHRob3VnaCB0aGVyZSBpcyBhbHNvIGNvbnNpZGVyYWJsZSBkaXNwYXJpdHkgaW4gdGhlIG90aGVyIHR3byBkZXBhcnRtZW50cy4NCg0KYGBge3IsZmlnLmFsdD0ibW9zYWljIHBsb3Qgb2YgZGVwYXJ0bWVudCh4KSB2cyBnZW5kZXIoeSkifQ0KbW9zYWljcGxvdCgNCiAgdGFibGUoRW1wbG95ZWUkRGVwYXJ0bWVudCwNCiAgICAgICAgRW1wbG95ZWUkR2VuZGVyKSwNCiAgbWFpbiA9ICJEZXBhcnRtZW50IHZzLiBHZW5kZXIiLA0KICBvZmYgPSA0LA0KICBib3JkZXIgPSAid2hpdGUiLA0KICBjb2xvciA9IDE6MiwNCiAgbGFzID0gMSwNCiAgY2V4LmF4aXMgID0gMQ0KKQ0KYGBgDQoNCiMjIyBBdHRyaXRpb24gdnMuIHllYXJzIGF0IGNvbXBhbnkNCg0KPlRvIGdldCBhIHNlbnNlIG9mIHR5cGljYWxseSBob3cgbG9uZyBhbiBlbXBsb3llZSBzdGF5cyBpbiBhIGNvbXBhbnksIEkgZHJhdyBhIEthcGxhbi1NZWllciBzdXJ2aXZhbCBjdXJ2ZSBvZiBlbXBsb3llZXMsIGFzIHNob3duIGluIHRoZSBncmFwaCBiZWxvdy4NCg0KYGBge3IsZmlnLmFsdD0iS2FwbGFuLU1laWVyIHN1cnZpdmFsIGN1cnZlIGZvciBlbXBsb3llZSBzdGF5aW5nIHdpdGhpbiB0aGUgY29tcGFueS4geCBheGlzIHN0YW5kcyBmb3IgeWVhcnMgaW4gY29tcGFueSwgYW5kIHl4aXMgc3RhbmRzIGZvciB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgZW1wbG95ZWUgc3RpbGwgc3RheXMgYXQgdGhlIGNvbXBhbnkifQ0KZXM8LUVtcGxveWVlJT4lDQogIG11dGF0ZShhdHRyaXRpb249aWZlbHNlKEF0dHJpdGlvbj09IllFUyIsMCwxKSkNCmttPC1zdXJ2Zml0KFN1cnYoWWVhcnNBdENvbXBhbnksYXR0cml0aW9uKX4xLGRhdGE9ZXMpDQpwbG90KGttLGNvbmYuaW50PUZBTFNFLG1haW49IkthcGxhbi1NZWllciBzdXJ2aXZhbCBjdXJ2ZSBvZiBFbXBsb3llZSIseGxhYj0iWWVhcnMgYXQgY29tcGFueSIseWxhYj0iTm9uLWF0dHJpdGlvbiBwcm9iYWJpbGl0eSIpDQpgYGANCg0KPlRoZSB4LWF4aXMgc3RhbmRzIGZvciB5ZWFycyBhdCBhIGNvbXBhbnkgZm9yIGFuIGluZGl2aWR1YWwsIGFuZCB0aGUgeS1heGlzIHN0YW5kcyBmb3IgdGhlIHByb3BvcnRpb24gb2YgZW1wbG95ZWVzIHRoYXQgc3RpbGwgc3RheXMgYXQgdGhlIGNvbXBhbnksIG9yIHRoZSAic3Vydml2YWwiIHJhdGUgb2YgZW1wbG95ZWVzLiBNYXRoZW1hdGljYWxseSwgd2UgY291bGQgcmVwcmVzZW50IGl0IGFzICRQKFN1cnZpdmFsKT0xLVAoe0F0dHJpdGlvbn0pJCAgRnJvbSB0aGUgY3VydmUsIHdlIGZpbmQgdGhhdCBhYm91dCBoYWxmIG9mIGFsbCBlbXBsb3llZXMgbGVhdmUgdGhlIGNvbXBhbnkgd2l0aGluIDUgeWVhcnMsIGFuZCBvbmx5IDIwJSBvZiBhbGwgZW1wbG95ZWVzIHdpbGwgc3RheSB3aXRoaW4gdGhlIGNvbXBhbnkgZm9yIHRlbiB5ZWFycy4NCg0KIyMgMi4gUmVsYXRpb25zaGlwIGJldHdlZW4gYXR0cml0aW9uIGFuZCBJbmNvbWUNCg0KPk9uZSBiaWcgZmFjdG9yIHRoYXQgYW4gZW1wbG95ZWUgcXVpdHMgdGhlIGNvbXBhbnkgaXMgdGhhdCB0aGV5IGFyZSBub3Qgc2F0aXNmaWVkIHdpdGggdGhlaXIgaW5jb21lIGFuZCBzZWVrIHRvIGZpbmQgb3RoZXIgam9icyB3aXRoIGhpZ2hlciBpbmNvbWUgcHJvc3BlY3RzLiBGb3IgdGhpcyByZWFzb24sIHdlIHdpc2ggdG8gZXhwbG9yZSB0aGUgb3ZlcmFsbCBpbmNvbWUgc3RhdHVzIG9mIGVtcGxveWVlcy4gTm90ZTogYXMgdGhlIEthZ2dsZSBkYXRhc2V0IGRpZCBub3QgcHJvdmlkZSB0aGUgY3VycmVuY3kgdW5pdCBmb3IgaW5jb21lLCB3ZSB3aWxsIGFsc28gbm90IGluY2x1ZGUgdW5pdHMgZm9yIGluY29tZSBpbiBvdXIgYW5hbHlzaXMuDQoNCmBgYHtyLCBmaWcuYWx0PSAiVGhlIG1vbnRobHkgaW5jb21lIGRpc3RyaWJ1dGlvbnMgaW4gdGhlIGRhdGFzZXQgdXNpbmcgYSBkZW5zaXR5IHBsb3Qgd2l0aCB0aGUgYnJvd24gbGluZSBzaG93aW5nIHRoZSBtZWFuIG1vbnRobHkgaW5jb21lIGZvciBhbGwgd29ya2VycyIgfQ0KIEVtcF9hdHQgPC0gRW1wbG95ZWUgJT4lIA0KICBncm91cF9ieShBdHRyaXRpb24pICU+JQ0KICBzdW1tYXJpemUoYXZlX2luY29tZV9hdHQgPSBtZWFuKE1vbnRobHlJbmNvbWUpKQ0KDQpFbXBsb3llZSAlPiUgDQogIGxlZnRfam9pbihFbXBfYXR0LCANCiAgICAgICAgICAgIGJ5ID0gIkF0dHJpdGlvbiIpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBNb250aGx5SW5jb21lLCBjb2xvciA9IEF0dHJpdGlvbikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4pLCBjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAiZ3JheTY1IiwgYmlucyA9IDQwKSArDQogIGZhY2V0X3dyYXAodmFycyhBdHRyaXRpb24pKSArIA0KICAjIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBhdmVfaW5jb21lX2F0dCksIGNvbG9yID0gIiM0RjJDMURGRiIsIHNpemUgPSAxLjUpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhPS41LCBmaWxsPSIjMDA2NzQ3RkYiKSArIA0KICBsYWJzKHRpdGxlID0gIk1vbnRobHkgSW5jb21lIERpc3RyaWJ1dGlvbnMgYW5kIEF0dHJpdGlvbiBTaXR1YXRpb24iLCANCiAgICAgICBzdWJ0aXRsZSA9ICJEZW5zaXR5IFBsb3QiLA0KICAgICAgIHggPSBOVUxMLA0KICAgICAgIHkgPSBOVUxMKSArIA0KIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKQ0KDQogRW1wbG95ZWUgJT4lIA0KICBncm91cF9ieShBdHRyaXRpb24pICU+JQ0KICBzdW1tYXJpemUoYXZlX2luY29tZV9hdHQgPSBtZWFuKE1vbnRobHlJbmNvbWUpKSANCmBgYA0KDQo+VGhlIGFib3ZlIGhpc3RvZ3JhbSBkZXNjcmliZXMgdGhlIG92ZXJhbGwgaW5jb21lIGRpc3RyaWJ1dGlvbiBieSBhdHRyaXRpb24gc3RhdHVzLCB3aXRoIHRoZSBzbW9vdGhlZCBncmVlbiBkZW5zaXR5LiBPdmVyYWxsLCB3ZSBvYnNlcnZlIGEgZ29vZCBhbW91bnQgb2YgaW5jb21lIGRpc3Bhcml0eeKAk3RoZSBza2V3ZWQgZGlzdHJpYnV0aW9uIHNob3dzIHRoYXQgbW9zdCB3b3JrZXJzIHJlY2VpdmUgYSBtb250aGx5IGluY29tZSBsb3dlciB0aGFuIHRoZSBhdmVyYWdlLCB3aGlsZSBhIGZldyBwZW9wbGUgcmVjZWl2ZSBhIG1vbnRobHkgaW5jb21lIGZhciBoaWdoZXIgdGhhbiB0aGUgYXZlcmFnZSBpbmNvbWUgaW4gdGhpcyBjb21wYW55LiBJbiBhZGRpdGlvbiwgd2UgZmluZCB0aGF0IHRoZSBpbmNvbWUgZGlzcGFyaXR5IHNlZW1zIG1vcmUgZXh0cmVtZSB3aXRoaW4gdGhlIGF0dHJpdGVkIGVtcGxveWVlcyB3aXRoIG11Y2ggZ3JlYXRlciBza2V3bmVzcyBhbmQgZ3JlYXRlciBwZXJjZW50YWdlIGVhcm5pbmcgbGVzcyB0aGFuIDUsMDAwIGEgbW9udGgsIGFuZCB2ZXJ5IHNtYWxsIHBlcmNlbnRhZ2Ugb2YgZW1wbG95ZWVzIGVhcm5pbmcgb3ZlciAxMCwwMDAgbGVmdCB0aGUgY29tcGFueS4gVGhpcyBwcm92aWRlcyBjZXJ0YWluIGV2aWRlbmNlIHRoYXQgaW5jb21lIHByb3NwZWN0cyBhcmUgcXVpdGUgcmVsYXRlZCB3aXRoIGF0dHJpdGlvbiBzdGF0dXMuDQoNCmBgYHtyLCBmaWcuYWx0PSAiVGhlIG1vbnRobHkgaW5jb21lIGRpc3RyaWJ1dGlvbnMgYnkgdGhyZWUgZGVwYXJ0bWVudHMgYW5kIGdlbmRlciB1c2luZyBhIGJveCBwbG90IHdpdGggdGhlIGJsdWUgbGluZSBzaG93aW5nIHRoZSBtZWFuIG1vbnRobHkgaW5jb21lIGJ5IGRlcGFydG1lbnQiIH0NCkVtcGxveWVlX2RlcCA8LSBFbXBsb3llZSAlPiUNCiAgZ3JvdXBfYnkoRGVwYXJ0bWVudCkgJT4lDQogIHN1bW1hcml6ZShhdmVfaW5jb21lX2RlcCA9IG1lYW4oTW9udGhseUluY29tZSkpDQoNCiBFbXBsb3llZSAlPiUgDQogICBsZWZ0X2pvaW4oRW1wbG95ZWVfZGVwLA0KICAgICAgICAgICAgIGJ5PSAiRGVwYXJ0bWVudCIpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBNb250aGx5SW5jb21lLCBjb2xvciA9IEF0dHJpdGlvbikpICsNCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC4yICkgKw0KICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gYXZlX2luY29tZV9kZXApLCBjb2xvciA9ICIjNEYyQzFERkYiLCBzaXplID0gMSkgKw0KICBmYWNldF93cmFwKHZhcnMgKERlcGFydG1lbnQpKSArIA0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiWWVzIiA9ICJncmF5NjUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm8iPSJicm93bjQiKSkgKyANCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IEluY29tZSBEaXN0cmlidXRpb25zIGJ5IGRlcGFydG1lbnQgYW5kIEF0dHJpdGlvbiBTaXR1YXRpb24iLCANCiAgICAgICBzdWJ0aXRsZSA9ICJCb3ggUGxvdCIsDQogICAgICAgeCA9IE5VTEwsDQogICAgICAgeSA9IE5VTEwpDQpgYGANCg0KPldlIHRoZW4gdGFrZSBhIHN0ZXAgZnVydGhlciBpbnRvIHRoZSBtb250aGx5IGluY29tZSBkaXN0cmlidXRpb24gYnkgZGVwYXJ0bWVudCBhbmQgYXR0cml0aW9uIHN0YXR1cy4gVGhlIGJveHBsb3RzIGFib3ZlIHNob3cgdGhhdCwgYW1vbmcgdGhlIHRocmVlIGRlcGFydG1lbnRzLCBodW1hbiByZXNvdXJjZXMgYW5kIHJlc2VhcmNoICYgZGV2ZWxvcG1lbnQgZGVwYXJ0bWVudHMgdGVuZCB0byBoYXZlIGdyZWF0ZXIgaW5jb21lIGluZXF1YWxpdHkgYXMgd2Ugc2VlIHJlbGF0aXZlbHkgbGFyZ2VyIGdhcHMgYmV0d2VlbiB0aGUgbWVkaWFuIGFuZCB0aGUgYXZlcmFnZSBpbmNvbWUgKHNob3duIGJ5IHRoZSBkYXJrIGJyb3duIGxpbmUpLiBBdCB0aGUgc2FtZSB0aW1lLCBpdCBzZWVtcyB0aGF0IGluIHRoZXNlIHR3byBkZXBhcnRtZW50cywgbm9uLWF0dHJpdGVkIGVtcGxveWVlcyB0ZW5kIHRvIGhhdmUgbXVjaCBoaWdoZXIgbW9udGhseSBpbmNvbWUgdGhhbiB0aG9zZSB3aG8gbGVmdCB0aGUgY29tcGFueS4gSW5jb21lIGluZXF1YWxpdHkgYW5kIGF0dHJpdGlvbi9ub24tYXR0cml0aW9uIGRpZmZlcmVudGlhbCBpcyBsZXNzIGV4dHJlbWUgZm9yIHRoZSBzYWxlcyBkZXBhcnRtZW50LCBidXQgdGhlIGxvd2VyLWludGVycXVhcnRpbGUgZGlmZmVyZW5jZSBpcyBzdGlsbCBzdWJzdGFudGlhbC4gT3ZlcmFsbCwgdGhlIHNhbGVzIGRlcGFydG1lbnQgaGFzIHRoZSBoaWdoZXN0IGF2ZXJhZ2UgbW9udGhseSBpbmNvbWUgNjk1OS4yLCB0aGUgaHVtYW4gcmVzb3VyY2VzIGRlcGFydG1lbnQgaGFzIHRoZSBzZWNvbmQgaGlnaGVzdCBhdmVyYWdlIG1vbnRobHkgaW5jb21lIDY2NTQuNSwgYW5kIHRoZSByZXNlYXJjaCAmIGRldmVsb3BtZW50IGRlcGFydG1lbnQgaGFzIHRoZSBsb3dlc3QgYXZlcmFnZSBtb250aGx5IGluY29tZSA2MjgxLjMuDQoNCj5JbiBhZGRpdGlvbiB0byB0aGUgY3VycmVudCBpbmNvbWUgc3RhdHVzLCBwcm9iYWJseSBldmVuIG1vcmUsIGVtcGxveWVlcyBjYXJlIGFib3V0IGhvdyBsaWtlbHkgdGhlaXIgaW5jb21lIHdvdWxkIGluY3JlYXNlIGluIHRoZSBmdXR1cmUuIFdlIHRodXMgZHJhdyB0aGUgc2NhdHRlciBwbG90IGJlbG93IHRvIHNob3cgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGF2ZXJhZ2UgbW9udGhseSBpbmNvbWUgYW5kIHllYXJzIGF0IGNvbXBhbnkuIElmIHdlIGlnbm9yZSB0aGUgb3V0bGllcnMgd2hvIGxlZnQgdGhlIGNvbXBhbnkgYWZ0ZXIgb3ZlciAzMCB5ZWFycyBzZXJ2aW5nIGZvciB0aGUgY29tcGFueSwgd2UgZmluZCB0aGF0IHRoZSBwcm9zcGVjdCBvZiBwYXkgcmFpc2UgaXMgcm91Z2hseSB0aGUgc2FtZSBiZXR3ZWVuIHRob3NlIGJvdGggYXR0cml0aW9uIGdyb3VwcywgYXMgd2Ugc2VlIGEgcm91Z2hseSBwYXJhbGxlbCB0cmVuZC4NCg0KYGBge3IsIGZpZy5hbHQ9IkF2ZXJhZ2UgbW9udGhseSBpbmNvbWUgdnMuIFllYXJzIGF0IGNvbXBhbnkgIn0NCkVtcGxveWVlICU+JQ0KICBncm91cF9ieShEZXBhcnRtZW50LFllYXJzQXRDb21wYW55LEF0dHJpdGlvbikgJT4lDQogIHN1bW1hcml6ZShgQXZlcmFnZSBpbmNvbWVgID0gbWVhbihNb250aGx5SW5jb21lKSkgJT4lDQogIGdncGxvdChhZXMoeD1ZZWFyc0F0Q29tcGFueSkpICsNCiAgZ2VvbV9wb2ludChzaXplPTEsDQogICAgICAgICAgICBhZXMoIHk9YEF2ZXJhZ2UgaW5jb21lYCwNCiAgICAgICAgICAgIGNvbG9yPUF0dHJpdGlvbikpKw0KICBnZW9tX3Ntb290aChhZXMoeT1gQXZlcmFnZSBpbmNvbWVgLA0KICAgICAgICAgICAgIGNvbG9yPUF0dHJpdGlvbiksDQogICAgICAgICAgICAgc2UgPSBGQUxTRSxzaXplPTAuNykrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlllcyIgPSAiZ3JheTY1IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vIj0iYnJvd240IikpKw0KIyAgZmFjZXRfd3JhcCh+RGVwYXJ0bWVudCkrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgbGFicyh4PSdUb3RhbCB3b3JraW5nIHllYXJzJywNCiAgICAgICB0aXRsZSA9ICJBdmVyYWdlIG1vbnRobHkgaW5jb21lIHZzLiBZZWFycyBhdCBjb21wYW55ICIsDQogICAgICAgeT0iTW9udGhseSBpbmNvbWUiKQ0KYGBgDQoNCj5XZSBsb29rIG1vcmUgY2xvc2VseSBhdCB0aGUgcGVyY2VudCBzYWxhcnkgaGlrZSBieSBkZXBhcnRtZW50IGluIHRoZSBncm91cCBvZiBib3hwbG90cyBiZWxvdy4gVGhlIHJlc3VsdHMgY29ycm9ib3JhdGUgdGhlIHByZXZpb3VzIGdyYXBoLiBPdGhlciB0aGFuIHRoZSBodW1hbiByZXNvdXJjZXMgZGVwYXJ0bWVudCB3aGljaCBoYXZlIHRoZSBmZXdlc3QgZW1wbG95ZWVzLCBpbiBib3RoIFImRCBhbmQgU2FsZXMgZGVwYXJ0bWVudHMsIHRoZSBpbmNvbWUgcHJvc3BlY3RzIGZvciB0aG9zZSB3aG8gaGF2ZSBhbmQgaGF2ZW7igJl0IGxlZnQgdGhlIGNvbXBhbnkgaXMgYXBwcm94aW1hdGVseSB0aGUgc2FtZSwgd2l0aCB2ZXJ5IHNpbWlsYXIgbWVkaWFuLCBtZWFuLCBhbmQgaW50ZXJxdWFydGlsZSBzYWxhcnkgaGlrZSBwZXJjZW50YWdlLiBUaHVzLCBmcm9tIHRoaXMgZGF0YSwgd2UgZG9u4oCZdCB0aGluayBmdXR1cmUgaW5jb21lIHByb3NwZWN0cyBwbGF5IGFzIGh1Z2UgYSByb2xlIGluIGF0dHJpdGlvbiBzdGF0dXMgYXMgdGhlIGN1cnJlbnQgaW5jb21lLg0KDQpgYGB7ciwgZmlnLmFsdD0iUGVyY2VudCBTYWxhcnkgSGlrZSBieSBEZXBhcnRtZW50IGFuZCBBdHRyaXRpb24ifQ0KRW1wbG95ZWUgJT4lDQogIGdncGxvdChhZXMoeT1QZXJjZW50U2FsYXJ5SGlrZSx4PUF0dHJpdGlvbiwgY29sb3I9QXR0cml0aW9uKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjIgKSsNCiAgZmFjZXRfd3JhcCh+RGVwYXJ0bWVudCkrDQogICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiWWVzIiA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJObyI9ImJyb3duNCIpKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICBsYWJzKHRpdGxlID0gIlBlcmNlbnQgU2FsYXJ5IEhpa2UgYnkgRGVwYXJ0bWVudCBhbmQgQXR0cml0aW9uIix5PSIiKQ0KYGBgDQoNCiMjIDMuIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIEpvYiBTYXRpc2ZhY3Rpb24gYW5kIEF0dHJpdGlvbg0KDQo+UHJvYmFibHkgZXZlbiBtb3JlIGltcG9ydGFudCB0aGFuIGluY29tZSwgZW1wbG95ZWVz4oCZIG92ZXJhbGwgam9iIHNhdGlzZmFjdGlvbiByYXRpbmdzIGNvdWxkIHBvdGVudGlhbGx5IHRlbGwgbW9yZSBhYm91dCB3aGV0aGVyIHRoZXkgYXJlIGhhcHB5IHdpdGggdGhlaXIgam9iLiBXZSB0aHVzIGFsc28gd2lzaCB0byBleHBsb3JlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhdHRyaXRpb24gYW5kIGpvYiBzYXRpc2ZhY3Rpb24uIEluIG91ciBkYXRhc2V0LCBqb2IgcmF0aW5nIGhhcyBmb3VyIGxldmVsczogMSBtZWFuaW5nIOKAnGxvdyzigJ0gMiBtZWFuaW5nIOKAnG1lZGl1bSzigJ0gMyBtZWFuaW5nIOKAnGhpZ2gs4oCdIDQgbWVhbmluZyDigJx2ZXJ5IGhpZ2gu4oCdDQoNCmBgYHtyLCBmaWcuYWx0PSJKb2IgU2F0aXNmYWN0aW9uIGJ5IERlcGFydG1lbnQgQW5kIEF0dHJpdGlvbiBTdGF0dXMifQ0KbmV3RW1wbG95ZWVBdHRyaXRpb24gPC0gRW1wbG95ZWUgJT4lDQogIGdyb3VwX2J5KERlcGFydG1lbnQsSm9iU2F0aXNmYWN0aW9uLEF0dHJpdGlvbikgJT4lDQogIHN1bW1hcmlzZShudW1iZXIgPSBuKCkpDQoNCm5ld0VtcGxveWVlQXR0cml0aW9uUGxvdDwtIG5ld0VtcGxveWVlQXR0cml0aW9uICAlPiUgDQogIGdncGxvdChhZXMoeCA9IEpvYlNhdGlzZmFjdGlvbiwgeSA9IG51bWJlcix0ZXh0ID0gcGFzdGUoJ051bWJlciBvZiBQZW9wbGUgOicsIG51bWJlcikpICkrDQogIGdlb21fY29sKGFlcyggZmlsbCA9IEF0dHJpdGlvbikpICsNCiAgZmFjZXRfZ3JpZCgufkRlcGFydG1lbnQpKw0KICBsYWJzKHRpdGxlID0gIkpvYiBTYXRpc2ZhY3Rpb24gYnkgRGVwYXJ0bWVudCBBbmQgQXR0cml0aW9uIFN0YXR1cyIsDQogICAgICAgeCA9IE5VTEwsDQogICAgICAgeSA9IE5VTEwsDQogICAgICAgZmlsbD1OVUxMKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoImZpcmVicmljazMiLCAiYmxhY2siKSwNCiAgICBsYWJlbHMgPSBjKCJOb3QgQXR0cml0ZWQiLCAiQXR0cml0ZWQiKQ0KICApICsNCiB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDExKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjEsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoDQogICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgaGp1c3QgPSAyLA0KICAgICAgdmp1c3QgPSAyDQogICAgKQ0KICApDQoNCg0KYGBgDQoNCmBgYHtyLCBmaWcuYWx0PSJKb2IgU2F0aXNmYWN0aW9uIGJ5IERlcGFydG1lbnQgQW5kIEF0dHJpdGlvbiBTdGF0dXMifQ0KZ2dwbG90bHkobmV3RW1wbG95ZWVBdHRyaXRpb25QbG90LCB0b29sdGlwID0gYygidGV4dCIpICkNCmBgYA0KDQo+V2hlbiBsb29raW5nIGF0IGpvYiBzYXRpc2ZhY3Rpb24sIGl0IGlzIHVuc3VycHJpc2luZyB0aGF0IHRoZSBlbXBsb3llZXMgd2hvIHJhdGVkIOKAnDHigJ0gd291bGQgbW9yZSB0ZW5kIHRvIGxlYXZlIHRoZSBjb21wYW55IGluIGdlbmVyYWwuIEluIGFkZGl0aW9uLCBmb3IgdGhlIGh1bWFuIHJlc291cmNlcyBkZXBhcnRtZW50LCBoYWxmIG9mIHRoZSBlbXBsb3llZXMgcmF0ZWQg4oCcMeKAnSBhdHRyaXRlZC4gSG93ZXZlciwgaXQgaXMgaW50ZXJlc3RpbmcgdG8gbm90ZSB0aGF0IHRoZXJlIGFyZSBldmVuIGxlc3MgZW1wbG95ZWVzIGF0dHJpdGVkIHdpdGggcmF0aW5nIOKAnDLigJ0gdGhhbiBvdGhlciB0d28gaGlnaGVyIHJhdGluZ3MuIE1vcmVvdmVyLCBmb3IgdGhlIG90aGVyIHR3byBkZXBhcnRtZW50cywgYWx0aG91Z2ggdGhlIGF0dHJpdGlvbiBkZWNyZWFzZXMgd2l0aCB0aGUgaW5jcmVhc2Ugb2YgcmF0aW5nLCB0aGUgYXR0cml0aW9uIGRpZmZlcmVuY2VzIGFtb25nIGRpZmZlcmVudCByYXRpbmdzIGFyZSBub3QgZXhwbGljaXQuIFRodXMsIGpvYiBzYXRpc2ZhY3Rpb24gbWlnaHQgbm90IGJlIGEgdmVyeSBpbmZvcm1hdGl2ZSBpbmZsdWVuY2Ugd2hlbiBldmFsdWF0aW5nIHRoZSBhdHRyaXRpb24uIFNvbWUgcG9zc2libGUgZXhwbGFuYXRpb25zIG1pZ2h0IGJlIHRoYXQgZW1wbG95ZWVz4oCZIHJhdGluZyBtaWdodCB2YXJ5IG92ZXIgdGltZSBvciBzb21lIG1pZ2h0IG5vdCB0cmVhdCB0aGUgcmF0aW5nIHNlcmlvdXNseSBlbm91Z2ggdG8gcmVzcG9uZCB3aXRoIGEgdmFsaWQgdmFsdWUuDQoNCiNDb25jbHVzaW9uDQoNCj5FbXBsb3llZSBhdHRyaXRpb24gaXMgYW4gaW1wb3J0YW50IHBpZWNlIG9mIGluZm9ybWF0aW9uIHRvIGtlZXAgdHJhY2sgb2YgZm9yIGFueSBsYXJnZSBjb21wYW55LCBhcyBpdCBkZWVwbHkgY29uY2VybnMgZW1wbG95ZWVz4oCZIG1vcmFsZSwgd29yayBlbnZpcm9ubWVudCwgYW5kIHByb2R1Y3Rpb24gY29udGludWl0eSBvZiB0aGUgb3JnYW5pemF0aW9uLiBJbiBvdXIgS2FnZ2xlIGRhdGFzZXQsIG92ZXJhbGwsIHdlIGZpbmQgdGhhdCBlbXBsb3llZSBhdHRyaXRpb24gYXBwZWFycyB0byBoYXZlIHRoZSBncmVhdGVzdCBjb3JyZWxhdGlvbiB3aXRoIGluY29tZSBsZXZlbHMsIHdoaWxlIGZ1dHVyZSBpbmNvbWUgcHJvc3BlY3RzIGFuZCBqb2Igc2F0aXNmYWN0aW9uIHJhdGluZ3Mgc2VlbSBsZXNzIGltcG9ydGFudCBmYWN0b3JzLiBUaGlzIGhhcyBiZWVuIGluZm9ybWF0aXZlIGZvciB1cyBhbmQgZXNwZWNpYWxseSBmb3IgaHVtYW4gcmVzb3VyY2VzIHRvIHVuZGVyc3RhbmQgdGhlIGdlbmVyYWwgdHJlbmQgYW5kIGV4cGxhbmF0b3J5IGZhY3RvcnMgb2YgZW1wbG95ZWUgYXR0cml0aW9uLiANCg0KPkhvd2V2ZXIsIHdlIGFsc28gYWRtaXR0ZWRseSBmYWNlIGxpbWl0YXRpb25zIHdpdGggb3VyIGRhdGFzZXQuIEZpcnN0LCB3aGlsZSB3ZSBhcHByZWNpYXRlIHRoYXQgdGhlIGZpY3Rpb25hbCBkYXRhc2V0IHByb3RlY3RzIGluZGl2aWR1YWwgcHJpdmFjeSwgYXMgd2UgY2Fubm90IGlkZW50aWZ5IGFueSBzcGVjaWZpYyBjb21wYW55LCB3ZSBkb27igJl0IGtub3cgaG93IHR5cGljYWwgb3VyIGRhdGEgaXMgYW5kIGlmIHRoZSBkYXRhIGNhbiB3ZWxsIHJlcHJlc2VudCBhbGwgc2ltaWxhciBiaW9tZWRpY2FsIGNvbXBhbmllcy4gU2Vjb25kLCBzaW5jZSB3ZSBjYW5ub3QgdHJhY2sgd2hldGhlciBhdHRyaXRpb24gaXMgdm9sdW50YXJ5IG9yIG5vdCwgd2UgZmFjZSByZXN0cmljdGlvbnMgaW4gZHJhd2luZyBtb3JlIG1lYW5pbmdmdWwgY29uY2x1c2lvbnMgZnJvbSBvdXIgZGF0YS4gSWYgd2Ugd2VyZSBhYmxlIHRvIGxvY2F0ZSB0aGUgZGF0YSBtb3JlIHNwZWNpZmljYWxseSBhdCB2b2x1bnRhcnkgYXR0cml0aW9uLCB3ZSBtaWdodCBiZSBhYmxlIHRvIG1vcmUgY2xvc2VseSBpZGVudGlmeSBwb3RlbnRpYWwgcmVhc29ucyBmcm9tIHRoZSBjb21wYW5pZXPigJkgc2lkZSBmb3IgZW1wbG95ZWVzIHF1aXR0aW5nLiBGaW5hbGx5LCBnaXZlbiB0aGF0IG91ciBkYXRhc2V0LCB3aGlsZSByZWFzb25hYmx5IGxhcmdlIGVub3VnaCBmb3IgdXMgdG8gbWFrZSB2aXN1YWwgcmVwcmVzZW50YXRpb25zLCBkb2VzIG5vdCBjb250YWluIHF1aXRlIG1hbnkgYXR0cml0ZWQgZGF0YSBwb2ludHMoYWJvdXQgb3ZlciAyMDApLCBhbmQgY29udGFpbnMgb25seSB0aHJlZSBkZXBhcnRtZW50cyAoU2FsZXMsIFImRCwgSHVtYW4gcmVzb3VyY2VzKSwgd2UgY291bGRu4oCZdCByZWFzb25hYmx5IGluY2x1ZGUgYWxsIG9yIGFzIG1hbnkgdmFyaWFibGVzIGFzIHdlIGRlc2lyZSwgYXMgdGhhdCB3b3VsZCBsZWF2ZSB0b28gZmV3IGRhdGEgcG9pbnRzIGluIGVhY2ggZ3JvdXAuIA0KDQo=